﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SPMS.Utility;
using System.Xml;
using System.Xml.Schema;
using System.IO;
using SPMS.Commons.Logging;

namespace SPMS.Commons.Configuration.Xml
{
    /// <summary>
    /// XML配置对象工厂
    /// </summary>
    /// <remarks>用于创建XML配置对象</remarks>
    /// <history>
    /// [zanezeng]               2010/1/15 11:22    创建
    /// </history>
    public sealed class XmlConfigurationFactory : IConfigurationFactory
    {
        #region ---Constructor

        /// <summary>
        /// 初始化类型<see cref="XmlConfigurationFactory"/>的新实例
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/15 17:42    创建
        /// </history>
        public XmlConfigurationFactory()
        {
        }

        /// <summary>
        /// 初始化类型<see cref="XmlConfigurationFactory"/>的新实例
        /// </summary>
        /// <param name="schemaSet">用于验证XML架构的<see cref="XmlSchemaSet"/>对象。</param>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/15 17:43    创建
        /// </history>
        public XmlConfigurationFactory( XmlSchemaSet schemaSet )
        {
            //保存验证框架信息
            this.m_SchemaSet = schemaSet;
        }

        #endregion

        #region ---IConfigurationFactory

        /// <summary>
        /// 将给定统一资源描述符（<see cref="Uri"/>）指定的资源加载为配置对象
        /// </summary>
        /// <param name="resource">通过统一资源描述符（<see cref="Uri"/>）指定的配置资源</param>
        /// <returns>加载了给定资源的配置对象。如果加载失败，则返回空白的配置对象。</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/15 11:18    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/15 11:55    创建
        /// </history>
        public IConfiguration Load( Uri resource )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( resource, "resource" );

            //创建XML配置对象
            XmlConfiguration configuration = new XmlConfiguration( this.m_SchemaSet );

            try
            {
                //加载配置信息
                configuration.Load( resource );
            }
            catch (Exception ex)
            {
                //输出日志
                if (LOG.IsErrorEnabled)
                {
                    LOG.Error( ex, "从通过统一资源描述符'{0}'自定的资源中加载XML配置信息失败", resource );
                }
            }

            //返回配置对象
            return configuration;
        }

        /// <summary>
        /// 将给定文件名称指定的资源加载为配置对象
        /// </summary>
        /// <param name="fileName">包含配置资源的文件名称</param>
        /// <returns>加载了给定资源的配置对象。如果加载失败，则返回空白的配置对象。</returns>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="fileName"/>为<c>null</c>引用或者为空字符串。</exception>
        /// <history>
        /// [zanezeng]               2010/1/15 11:18    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/15 12:08    创建
        /// </history>
        public IConfiguration Load( string fileName )
        {
            //断言参数
            ArgumentAssert.AssertStringArgumentNotNullOrEmpty( fileName, "fileName" );

            //创建XML配置对象
            XmlConfiguration configuration = new XmlConfiguration( this.m_SchemaSet );

            try
            {
                //加载配置信息
                configuration.Load( fileName );
            }
            catch (Exception ex)
            {
                //输出日志
                if (LOG.IsErrorEnabled)
                {
                    LOG.Error( ex, "从文件'{0}'加载XML配置信息失败", fileName );
                }
            }

            //返回配置对象
            return configuration;
        }

        /// <summary>
        /// 将给定文件资源对象中加载为配置对象
        /// </summary>
        /// <param name="resource">包含配置信息的资源对象</param>
        /// <returns>加载了给定资源的配置对象。如果加载失败，则返回空白的配置对象。</returns>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="resource"/>为<c>null</c>引用。</exception>
        /// <history>
        /// [zanezeng]               2010/1/15 12:07    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/15 12:08    创建
        /// </history>
        public IConfiguration Load( object resource )
        {
            //断言参数
            ArgumentAssert.AssertArgumentNotNull( resource, "resource" );

            //创建XML配置对象
            XmlConfiguration configuration = new XmlConfiguration( this.m_SchemaSet );

            try
            {
                //判断是否为XML节点对象
                if (resource is XmlNode)
                {
                    //从XML节点中加载配置信息
                    configuration.Load( (XmlNode)resource );
                }
                //判断是否为流对象
                else if (resource is Stream)
                {
                    //从流中加载配置信息
                    configuration.Load( (Stream)resource );
                }
                //判断是否为XML读取对象
                else if (resource is XmlReader)
                {
                    //从XML读取器中加载配置信息
                    configuration.Load( (XmlReader)resource );
                }
                //判断是否为文本读取对象
                else if (resource is TextReader)
                {
                    //从文本读取器中加载配置信息
                    configuration.Load( (TextReader)resource );
                }
                //默认转换为字符串进行处理
                else
                {
                    //创建XML文档对象
                    XmlDocument document = new XmlDocument();

                    //加载XML资源
                    document.LoadXml( (string)resource );

                    //从XML文档中加载配置信息
                    configuration.Load( document );
                }
            }
            catch (Exception ex)
            {
                //输出日志
                if (LOG.IsErrorEnabled)
                {
                    LOG.Error( ex, "从资源对象'{0}'加载XML配置信息失败", resource );
                }
            }

            //返回配置对象
            return configuration;
        }

        #endregion

        #region ---Field

        /// <summary>
        /// XML配置架构信息
        /// </summary>
        private XmlSchemaSet m_SchemaSet;

        /// <summary>
        /// 日志对象
        /// </summary>
        private static readonly ILog LOG = LogFactory.GetLog<XmlConfigurationFactory>();

        #endregion
    }
}
